load("@bazel_skylib//lib:paths.bzl", "paths")
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
load("@bazel_skylib//rules:copy_file.bzl", "copy_file")
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("@rules_cc//cc:cc_shared_library.bzl", "cc_shared_library")
load("//lcm-bazel/private:copts.bzl", "WARNINGS_COPTS")
load("//lcm-bazel/private:expand_flag_template.bzl", "expand_flag_template")

package(
    default_applicable_licenses = ["//:license"],
    default_visibility = ["//visibility:private"],
)

# The following constants are congruent with the CMakeLists.txt.

LCM_SOURCES = [
    "eventlog.c",
    "lcm.c",
    "lcm_file.c",
    "lcm_memq.c",
    "lcm_mpudpm.c",
    "lcm_tcpq.c",
    "lcm_udpm.c",
    "ringbuffer.c",
    "udpm_util.c",
    "lcmtypes/channel_port_map_update_t.c",
    "lcmtypes/channel_to_port_t.c",
]

LCM_INSTALL_HEADERS = [
    "eventlog.h",
    "lcm.h",
    "lcm_c_namespace.h",
    "lcm_coretypes.h",
    "lcm_version.h",
    "lcm-cpp.hpp",
    "lcm-cpp-impl.hpp",
    "lcm_export.h",
]

LCM_SOURCES_WIN32 = [
    "windows/WinLCM.cpp",
    "windows/WinPorting.cpp",
]

LCM_INSTALL_HEADERS_WIN32 = [
    "windows/WinPorting.h",
]

LCM_LINKOPTS_WIN32 = [
    # TODO(jwnimmer-tri) Not sure yet how to do this in Bazel.
    # target_link_libraries(${lcm_lib} PRIVATE wsock32 ws2_32)
]

LCM_LINKOPTS_LINUX = [
    "-pthread",
]

LCM_COMPILE_DEFINITIONS_PRIVATE = [
    "_FILE_OFFSET_BITS=64",
    "_LARGEFILE_SOURCE",
    "_REENTRANT",
]

# Declare the libraries.

string_flag(
    name = "LCM_C_NAMESPACE",
    build_setting_default = "lcm",
)

expand_flag_template(
    name = "lcm_c_namespace.h",
    flag_substitutions = {
        "@LCM_C_NAMESPACE@": ":LCM_C_NAMESPACE",
    },
    template = "lcm_c_namespace.h.in",
)

LCM_PRIVATE_HEADERS = [
    "dbg.h",
    "ioutils.h",
    "lcm_internal.h",
    "ringbuffer.h",
    "udpm_util.h",
    "lcmtypes/channel_port_map_update_t.h",
    "lcmtypes/channel_to_port_t.h",
]

[
    # To obtain the correct include path for `<lcm/lcm.h>` and allow relative
    # include paths to our generated "lcm_c_namespace.h" header, we need to
    # copy all code to a subdir now and then set `strip_include_prefix` later.
    copy_file(
        name = "_copy_" + paths.basename(x),
        src = x,
        out = "copied/lcm/" + x,
    )
    for x in (
        LCM_INSTALL_HEADERS +
        LCM_INSTALL_HEADERS_WIN32 +
        LCM_PRIVATE_HEADERS +
        LCM_SOURCES +
        LCM_SOURCES_WIN32
    )
]

cc_library(
    name = "lcm-coretypes",
    hdrs = ["copied/lcm/lcm_coretypes.h"],
    strip_include_prefix = "/lcm/copied",
    visibility = ["//visibility:public"],
)

cc_library(
    name = "lcm-version",
    hdrs = ["copied/lcm/lcm_version.h"],
    strip_include_prefix = "/lcm/copied",
    visibility = ["//lcmgen:__pkg__"],
)

cc_library(
    name = "dbg-header-for-python",
    hdrs = ["dbg.h"],
    visibility = ["//lcm-python:__pkg__"],
)

config_setting(
    name = "linux",
    constraint_values = ["@platforms//os:linux"],
)

config_setting(
    name = "windows",
    constraint_values = ["@platforms//os:windows"],
)

SRCS = [
    "copied/lcm/" + x
    for x in LCM_SOURCES + LCM_PRIVATE_HEADERS
] + select({
    ":windows": [
        "copied/lcm/" + x
        for x in LCM_SOURCES_WIN32
    ],
    "//conditions:default": [],
})

HDRS = LCM_INSTALL_HEADERS + select({
    ":windows": LCM_INSTALL_HEADERS_WIN32,
    "//conditions:default": [],
})

cc_library(
    name = "_public_hdrs",
    hdrs = [
        "copied/lcm/" + x
        for x in LCM_INSTALL_HEADERS
    ] + select({
        ":windows": [
            "copied/lcm/" + x
            for x in LCM_INSTALL_HEADERS_WIN32
        ],
        "//conditions:default": [],
    }),
    strip_include_prefix = "/lcm/copied",
)

COPTS = [
    "-D" + x
    for x in LCM_COMPILE_DEFINITIONS_PRIVATE
] + WARNINGS_COPTS

LINKOPTS = select({
    ":linux": LCM_LINKOPTS_LINUX,
    "//conditions:default": [],
})

DEPS = [
    ":_public_hdrs",
    "@glib//glib",
]

cc_library(
    name = "lcm-shared",
    srcs = SRCS,
    hdrs = HDRS,
    copts = COPTS,
    linkopts = LINKOPTS,
    visibility = ["//visibility:public"],
    deps = DEPS,
)

cc_library(
    name = "lcm-static",
    srcs = SRCS,
    hdrs = HDRS,
    copts = COPTS,
    defines = ["LCM_STATIC"],
    linkopts = LINKOPTS,
    linkstatic = True,
    visibility = ["//visibility:public"],
    deps = DEPS,
)

cc_shared_library(
    name = "glib-2.0",
    visibility = ["//visibility:public"],
    deps = DEPS,
)

cc_shared_library(
    name = "lcm",
    dynamic_deps = [":glib-2.0"],
    visibility = ["//visibility:public"],
    deps = ["lcm-shared"],
)
